;;; core-evilify-keymap-ftest.el --- Spacemacs Functional Test File
;;
;; Copyright (c) 2012-2014 Sylvain Benner
;; Copyright (c) 2014-2015 Sylvain Benner & Contributors
;;
;; Author: Sylvain Benner <sylvain.benner@gmail.com>
;; URL: https://github.com/syl20bnr/spacemacs
;;
;; This file is not part of GNU Emacs.
;;
;;; License: GPLv3
(require 'mocker)
(require 'core-funcs)
(require 'core-evilify-keymap)
(require 'core-spacemacs-buffer)

;; ---------------------------------------------------------------------------
;; spacemacs|evilify-map
;; ---------------------------------------------------------------------------

;; commands

(ert-deftest test-evilify-map--s ()
  (let ((evil-evilified-state-map (let ((evil-map (make-sparse-keymap)))
                                    (define-key evil-map "s" 'evil-func)
                                    evil-map))
        (input-map (make-sparse-keymap)))
    (define-key input-map "s" 'func)
    (spacemacs|evilify-map input-map)
    (should (equal '((115 . func-or-evil-func--evilified-input-map-s)
                     (83 . func--evilified-input-map-S))
                   (spacemacs//evilify-sort-keymap input-map)))))

(ert-deftest test-evilify-map--s-2-evilified ()
  (let ((evil-evilified-state-map (let ((evil-map (make-sparse-keymap)))
                                    (define-key evil-map "s" 'evil-func)
                                    (define-key evil-map "S" 'evil-func2)
                                    evil-map))
        (input-map (make-sparse-keymap)))
    (define-key input-map "s" 'func)
    (spacemacs|evilify-map input-map)
    (should (equal '((115 . func-or-evil-func--evilified-input-map-s)
                     (83 . evil-func2--evilified-input-map-S)
                     (19 . func--evilified-input-map-C-s))
                   (spacemacs//evilify-sort-keymap input-map)))))

(ert-deftest test-evilify-map--s-S ()
  (let ((evil-evilified-state-map (let ((evil-map (make-sparse-keymap)))
                                    (define-key evil-map "s" 'evil-func)
                                    evil-map))
        (input-map (make-sparse-keymap)))
    (define-key input-map "s" 'func1)
    (define-key input-map "S" 'func2)
    (spacemacs|evilify-map input-map)
    (should (equal '((115 . func1-or-evil-func--evilified-input-map-s)
                     (83 . func2-or-func1--evilified-input-map-S)
                     (19 . func2--evilified-input-map-C-s))
                   (spacemacs//evilify-sort-keymap input-map)))))

(ert-deftest test-evilify-map--s-S-reversed-order ()
  (let ((evil-evilified-state-map (let ((evil-map (make-sparse-keymap)))
                                    (define-key evil-map "s" 'evil-func)
                                    evil-map))
        (input-map (make-sparse-keymap)))
    (define-key input-map "S" 'func2)
    (define-key input-map "s" 'func1)
    (spacemacs|evilify-map input-map)
    (should (equal '((115 . func1-or-evil-func--evilified-input-map-s)
                     (83 . func2-or-func1--evilified-input-map-S)
                     (19 . func2--evilified-input-map-C-s))
                   (spacemacs//evilify-sort-keymap input-map)))))

(ert-deftest test-evilify-map--s-S-2-evilified ()
  (let ((evil-evilified-state-map (let ((evil-map (make-sparse-keymap)))
                                    (define-key evil-map "s" 'evil-func1)
                                    (define-key evil-map "S" 'evil-func2)
                                    evil-map))
        (input-map (make-sparse-keymap)))
    (define-key input-map "s" 'func1)
    (define-key input-map "S" 'func2)
    (spacemacs|evilify-map input-map)
    (should (equal '((115 . func1-or-evil-func1--evilified-input-map-s)
                     (83 . func2-or-evil-func2--evilified-input-map-S)
                     (19 . func1--evilified-input-map-C-s)
                     (33554451 . func2--evilified-input-map-C-S-s))
                   (spacemacs//evilify-sort-keymap input-map)))))

(ert-deftest test-evilify-map--s-S-2-evilified-reversed-order ()
  (let ((evil-evilified-state-map (let ((evil-map (make-sparse-keymap)))
                                    (define-key evil-map "S" 'evil-func2)
                                    (define-key evil-map "s" 'evil-func1)
                                    evil-map))
        (input-map (make-sparse-keymap)))
    (define-key input-map "S" 'func2)
    (define-key input-map "s" 'func1)
    (spacemacs|evilify-map input-map)
    (should (equal '((115 . func1-or-evil-func1--evilified-input-map-s)
                     (83 . func2-or-evil-func2--evilified-input-map-S)
                     (19 . func1--evilified-input-map-C-s)
                     (33554451 . func2--evilified-input-map-C-S-s))
                   (spacemacs//evilify-sort-keymap input-map)))))

(ert-deftest test-evilify-map--s-S-C-s ()
  (let ((evil-evilified-state-map (let ((evil-map (make-sparse-keymap)))
                                    (define-key evil-map "s" 'evil-func)
                                    evil-map))
        (input-map (make-sparse-keymap)))
    (define-key input-map "s" 'func1)
    (define-key input-map "S" 'func2)
    (define-key input-map (kbd "C-s") 'func3)
    (spacemacs|evilify-map input-map)
    (should (equal '((115 . func1-or-evil-func--evilified-input-map-s)
                     (83 . func2-or-func1--evilified-input-map-S)
                     (19 . func3-or-func2--evilified-input-map-C-s)
                     (33554451 . func3--evilified-input-map-C-S-s))
                   (spacemacs//evilify-sort-keymap input-map)))))

(ert-deftest test-evilify-map--s-S-C-s-shuffled ()
  (let ((evil-evilified-state-map (let ((evil-map (make-sparse-keymap)))
                                    (define-key evil-map "s" 'evil-func)
                                    evil-map))
        (input-map (make-sparse-keymap)))
    (define-key input-map "s" 'func1)
    (define-key input-map (kbd "C-s") 'func3)
    (define-key input-map "S" 'func2)
    (spacemacs|evilify-map input-map)
    (should (equal '((115 . func1-or-evil-func--evilified-input-map-s)
                     (83 . func2-or-func1--evilified-input-map-S)
                     (19 . func3-or-func2--evilified-input-map-C-s)
                     (33554451 . func3--evilified-input-map-C-S-s))
                   (spacemacs//evilify-sort-keymap input-map)))))

(ert-deftest test-evilify-map--s-S-C-s-2-evilified ()
  (let ((evil-evilified-state-map (let ((evil-map (make-sparse-keymap)))
                                    (define-key evil-map "s" 'evil-func1)
                                    (define-key evil-map "S" 'evil-func2)
                                    evil-map))
        (input-map (make-sparse-keymap)))
    (define-key input-map "s" 'func1)
    (define-key input-map "S" 'func2)
    (define-key input-map (kbd "C-s") 'func3)
    (mocker-let
     ((spacemacs-buffer/warning (msg &rest args)
                                ((:record-cls 'mocker-stub-record
                                              :output nil :occur 1))))
     (spacemacs|evilify-map input-map)
     (should (equal '((115 . func1-or-evil-func1--evilified-input-map-s)
                      (83 . func2-or-evil-func2--evilified-input-map-S)
                      (19 . func3-or-func1--evilified-input-map-C-s)
                      (33554451 . func2--evilified-input-map-C-S-s))
                    (spacemacs//evilify-sort-keymap input-map))))))

(ert-deftest test-evilify-map--s-C-s-S-2-evilified-shuffled ()
  (let ((evil-evilified-state-map (let ((evil-map (make-sparse-keymap)))
                                    (define-key evil-map "s" 'evil-func1)
                                    (define-key evil-map "S" 'evil-func2)
                                    evil-map))
        (input-map (make-sparse-keymap)))
    (define-key input-map "s" 'func1)
    (define-key input-map (kbd "C-s") 'func3)
    (define-key input-map "S" 'func2)
    (mocker-let
     ((spacemacs-buffer/warning (msg &rest args)
                                ((:record-cls 'mocker-stub-record
                                              :output nil :occur 1))))
     (spacemacs|evilify-map input-map)
     (should (equal '((115 . func1-or-evil-func1--evilified-input-map-s)
                      (83 . func2-or-evil-func2--evilified-input-map-S)
                      (19 . func3-or-func1--evilified-input-map-C-s)
                      (33554451 . func2--evilified-input-map-C-S-s))
                    (spacemacs//evilify-sort-keymap input-map))))))

;; keymaps

(ert-deftest test-evilify-map--s-keymap ()
  (let ((evil-evilified-state-map (let ((evil-map (make-sparse-keymap)))
                                    (define-key evil-map "s" 'evil-func)
                                    evil-map))
        (input-map (make-sparse-keymap))
        (submap (make-sparse-keymap)))
    (define-key input-map "s" submap)
    (define-key submap "t" 'func)
    (spacemacs|evilify-map input-map)
    (should (equal '((115 . keymap-s-or-evil-func--evilified-input-map-s)
                     (83 . keymap-s--evilified-input-map-S))
                   (spacemacs//evilify-sort-keymap input-map)))))

(ert-deftest test-evilify-map--s-keymap-2-evilified ()
  (let ((evil-evilified-state-map (let ((evil-map (make-sparse-keymap)))
                                    (define-key evil-map "s" 'evil-func1)
                                    (define-key evil-map "S" 'evil-func2)
                                    evil-map))
        (input-map (make-sparse-keymap))
        (submap (make-sparse-keymap)))
    (define-key input-map "s" submap)
    (define-key submap "t" 'func)
    (spacemacs|evilify-map input-map)
    (should (equal '((115 . keymap-s-or-evil-func1--evilified-input-map-s)
                     (83 . evil-func2--evilified-input-map-S)
                     (19 . keymap-s--evilified-input-map-C-s))
                   (spacemacs//evilify-sort-keymap input-map)))))

(ert-deftest test-evilify-map--s-S-keymaps ()
  (let ((evil-evilified-state-map (let ((evil-map (make-sparse-keymap)))
                                    (define-key evil-map "s" 'evil-func)
                                    evil-map))
        (input-map (make-sparse-keymap))
        (submap (make-sparse-keymap)))
    (define-key input-map "s" submap)
    (define-key input-map "S" submap)
    (define-key submap "t" 'func)
    (spacemacs|evilify-map input-map)
    (should (equal '((115 . keymap-s-or-evil-func--evilified-input-map-s)
                     (83 . keymap-S-or-keymap-s--evilified-input-map-S)
                     (19 . keymap-S--evilified-input-map-C-s))
                   (spacemacs//evilify-sort-keymap input-map)))))

(ert-deftest test-evilify-map--s-S-keymaps-2-evilified ()
  (let ((evil-evilified-state-map (let ((evil-map (make-sparse-keymap)))
                                    (define-key evil-map "s" 'evil-func1)
                                    (define-key evil-map "S" 'evil-func2)
                                    evil-map))
        (input-map (make-sparse-keymap))
        (submap (make-sparse-keymap)))
    (define-key input-map "s" submap)
    (define-key input-map "S" submap)
    (define-key submap "t" 'func)
    (spacemacs|evilify-map input-map)
    (should (equal '((115 . keymap-s-or-evil-func1--evilified-input-map-s)
                     (83 . keymap-S-or-evil-func2--evilified-input-map-S)
                     (19 . keymap-s--evilified-input-map-C-s)
                     (33554451 . keymap-S--evilified-input-map-C-S-s))
                   (spacemacs//evilify-sort-keymap input-map)))))

(ert-deftest test-evilify-map--s-S-C-s-keymaps ()
  (let ((evil-evilified-state-map (let ((evil-map (make-sparse-keymap)))
                                    (define-key evil-map "s" 'evil-func)
                                    evil-map))
        (input-map (make-sparse-keymap))
        (submap (make-sparse-keymap)))
    (define-key input-map "s" submap)
    (define-key input-map "S" submap)
    (define-key input-map (kbd "C-s") submap)
    (define-key submap "t" 'func)
    (spacemacs|evilify-map input-map)
    (should (equal '((115 . keymap-s-or-evil-func--evilified-input-map-s)
                     (83 . keymap-S-or-keymap-s--evilified-input-map-S)
                     (19 . keymap-C-s-or-keymap-S--evilified-input-map-C-s)
                     (33554451 . keymap-C-s--evilified-input-map-C-S-s))
                   (spacemacs//evilify-sort-keymap input-map)))))

(ert-deftest test-evilify-map--s-S-C-s-keymaps-2-evilified ()
  (let ((evil-evilified-state-map (let ((evil-map (make-sparse-keymap)))
                                    (define-key evil-map "s" 'evil-func1)
                                    (define-key evil-map "S" 'evil-func2)
                                    evil-map))
        (input-map (make-sparse-keymap))
        (submap (make-sparse-keymap)))
    (define-key input-map "s" submap)
    (define-key input-map "S" submap)
    (define-key input-map (kbd "C-s") submap)
    (define-key submap "t" 'func)
    (mocker-let
     ((spacemacs-buffer/warning (msg &rest args)
                                ((:record-cls 'mocker-stub-record
                                              :output nil :occur 1))))
     (spacemacs|evilify-map input-map)
     (should (equal '((115 . keymap-s-or-evil-func1--evilified-input-map-s)
                      (83 . keymap-S-or-evil-func2--evilified-input-map-S)
                      (19 . keymap-C-s-or-keymap-s--evilified-input-map-C-s)
                      (33554451 . keymap-S--evilified-input-map-C-S-s))
                    (spacemacs//evilify-sort-keymap input-map))))))

;; commands and keymaps

(ert-deftest test-evilify-map--s-command-and-keymap ()
  (let ((evil-evilified-state-map (let ((evil-map (make-sparse-keymap)))
                                    (define-key evil-map "s" 'evil-func)
                                    evil-map))
        (input-map (make-sparse-keymap))
        (submap (make-sparse-keymap)))
    (define-key input-map "s" 'func)
    (define-key input-map "S" submap)
    (define-key submap "t" 'func)
    (spacemacs|evilify-map input-map)
    (should (equal '((115 . func-or-evil-func--evilified-input-map-s)
                     (83 . keymap-S-or-func--evilified-input-map-S)
                     (19 . keymap-S--evilified-input-map-C-s))
                   (spacemacs//evilify-sort-keymap input-map)))))

;; idem-potency

(ert-deftest test-evilify-map--idem-potent ()
  (let ((evil-evilified-state-map (let ((evil-map (make-sparse-keymap)))
                                    (define-key evil-map "s" 'evil-func)
                                    evil-map))
        (input-map (make-sparse-keymap))
        (submap (make-sparse-keymap)))
    (define-key input-map "e" 'func1)
    (define-key input-map (kbd "C-c C-x") 'func3)
    (define-key input-map "s" 'func2)
    (define-key input-map "S" submap)
    (define-key submap "t" 'func)
    (dotimes (_ 10)
      (spacemacs|evilify-map input-map))
    (should (equal '((115 . func2-or-evil-func--evilified-input-map-s)
                     (101 . func1)
                     (83 . keymap-S-or-func2--evilified-input-map-S)
                     (19 . keymap-S--evilified-input-map-C-s)
                     (3 . (keymap (24 . func3))))
                   (spacemacs//evilify-sort-keymap input-map)))))

